package q224_calculate;

import java.util.Deque;
import java.util.LinkedList;

public class Solution {

    /**
     * 使用一个取值为{−1,+1} 的整数 sign 代表「当前」的符号。根据括号表达式的性质，它的取值
     * 1 与字符串中当前位置的运算符有关
     * 2 如果当前位置处于一系列括号之内，则也与这些括号前面的运算符有关：每当遇到一个以 − 号开头的括号，则意味着此后的符号都要被「翻转」
     * @param s
     * @return
     */
    public int calculate(String s) {
        Deque<Integer> ops = new LinkedList<Integer>();
        ops.push(1);
        int sign = 1;

        int ret = 0;
        int n = s.length();
        int i = 0;
        while (i < n) {
            // 遇到空格跳过
            if (s.charAt(i) == ' ') {
                i++;
                // 遇到 + 时 将sign转为栈顶的的符号 也就是+并不影响接下来整体的正负
            } else if (s.charAt(i) == '+') {
                sign = ops.peek();
                i++;
            } else if (s.charAt(i) == '-') {
                // 同样的遇到 - 时 则需要将栈顶的符号反过来 因为 - 会导致接下来的整体反转
                sign = -ops.peek();
                i++;
            } else if (s.charAt(i) == '(') {
                // 遇到左括号时 此时要将对应的符号压入栈中 这会决定接下来该括号包括的整体的符号变化
                // 比如左括号前面是一个负号 栈顶就会被压入 -1 那么接下来该括号内的每一个符号都会利用这个-1相应的变化
                // 也就是上面的两个判断的作用
                ops.push(sign);
                i++;
            } else if (s.charAt(i) == ')') {
                // 遇到右括号时 也就意味着栈顶压入的符号作用结束了 所以要弹出
                ops.pop();
                i++;
            } else {
                // 需要注意的是 我们是利用字符串进行计算
                // 所以首先
                // 1 遇到某一个数字时 首先定义一个临时数字num 并且要是long类型防止溢出
                // 2 计算的方法就是 num = num * 10 + (s.charAt(i) - '0')
                // 当将该数字的值求出时 就需要将其加入到结果中
                // 此时就需要结合我们的符号进行判断 也就是sign
                long num = 0;
                while (i < n && Character.isDigit(s.charAt(i))) {
                    num = num * 10 + s.charAt(i) - '0';
                    i++;
                }
                ret += sign * num;
            }
        }
        return ret;
    }


}
